package com.electronic.modules.electronicSealSignature;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.ElectronicSealSignature;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.param.GetElectronicSealSignatureUserInfoParamDTO;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.param.GetUserSealsParamDTO;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.param.QueryQRCodeScannedStatusParamDTO;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.result.GenerateElectronicSealSignatureQRCodeResultDTO;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.result.GetElectronicSealSignatureUserInfoResultDTO;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.result.GetUserSealsResultDTO;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.result.QueryQRCodeScannedStatusResultDTO;
import com.electronic.api.R;
import com.electronic.constant.CebsConstant;
import com.electronic.constant.JwtConstant;
import com.electronic.domain.CebsConfiguration;
import com.electronic.domain.CebsSdkProperties;
import com.electronic.domain.SealSize;
import com.electronic.enums.FileTypeEnum;
import com.electronic.enums.PositionTypeEnum;
import com.electronic.enums.QRCodeScannedStatusEnum;
import com.electronic.enums.SealTypeEnum;
import com.electronic.exception.ResultCode;
import com.electronic.exception.ServiceException;
import com.electronic.jwt.JwtProvider;
import com.electronic.modules.electronicSealSignature.param.CebsSignatureDTO;
import com.electronic.modules.electronicSealSignature.param.CommitSignInfoDTO;
import com.electronic.modules.electronicSealSignature.param.StartSignDTO;
import com.electronic.modules.electronicSealSignature.result.*;
import com.electronic.utils.ICommonUtil;
import com.electronic.utils.IFCAUtil;
import com.electronic.utils.IRequestUtil;
import com.electronic.utils.pdf.PDFTools;
import com.itextpdf.text.pdf.PdfReader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Base64Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
public class ElectronicSealSignatureService {
    /**
     * 获取签章二维码
     * @param
     * @return
     */
    public static R<GetSignQrCodeVO> getSignatureQrCode(CebsSdkProperties cebsSdkProperties) {
        // 初始化Ca
        CebsConfiguration.init(cebsSdkProperties);
        //SDK返回对象
        GenerateElectronicSealSignatureQRCodeResultDTO resultDTO = null;
        try {
            //SDK返回对象
            resultDTO = ElectronicSealSignature.generateElectronicSealSignatureQRCode();
        } catch (Exception e) {
            throw new ServiceException(ResultCode.ERROR_SIGNATURE_QRCODE, ResultCode.ERROR_SIGNATURE_QRCODE.getMessage());
        }

        if (Objects.isNull(resultDTO)) {
            throw new ServiceException(ResultCode.ERROR_SIGNATURE_QRCODE,  ResultCode.ERROR_SIGNATURE_QRCODE.getMessage());
        }
        return R.data(GetSignQrCodeVO.convert(resultDTO));
    }

    /**
     * 获取二维码状态
     * @param qrCodeScanDTO
     * @return
     */
    public static GetQrCodeScanStatusVO getQrCodeScanStatus(QrCodeScanDTO qrCodeScanDTO) {
        // 初始化ca
        CebsConfiguration.init(qrCodeScanDTO.getCebsSdkProperties());
        //构造请求参数
        QueryQRCodeScannedStatusParamDTO paramDTO = new QueryQRCodeScannedStatusParamDTO();
        paramDTO.setTid(qrCodeScanDTO.getTid());

        QueryQRCodeScannedStatusResultDTO scannedStatusResultDTO = null;
        try {
            //SDK返回对象
            scannedStatusResultDTO = ElectronicSealSignature.queryQRCodeScannedStatus(paramDTO);
        } catch (Exception e) {
            throw new ServiceException(ResultCode.ERROR_SIGNATURE_QRCODE_STATUS, ResultCode.ERROR_SIGNATURE_QRCODE_STATUS.getMessage());
        }

        if (Objects.isNull(scannedStatusResultDTO)) {
            throw new ServiceException(ResultCode.ERROR_SIGNATURE_QRCODE_STATUS, ResultCode.ERROR_SIGNATURE_QRCODE_STATUS.getMessage());
        }

        GetQrCodeScanStatusVO vo = GetQrCodeScanStatusVO.convert(scannedStatusResultDTO);
        vo.setScannedDesc(QRCodeScannedStatusEnum.getDescByCode(vo.getScannedStatus()));
        //未完成扫码直接返回
        if (!QRCodeScannedStatusEnum.SIGNED.getCode().equals(vo.getScannedStatus())) {
             return vo;
        }

        //签章二维码已扫码，则获取签章用户信息
        GetElectronicSealSignatureUserInfoParamDTO userInfoParamDTO = new GetElectronicSealSignatureUserInfoParamDTO();
        userInfoParamDTO.setTid(vo.getTid());
        //已扫码签章用户信息
        GetElectronicSealSignatureUserInfoResultDTO userInfoResultDTO = null;
        try {
            //查询已扫码签章用户信息
              userInfoResultDTO = ElectronicSealSignature.getElectronicSealSignatureUserInfo(userInfoParamDTO);
        } catch (Exception e) {
            throw new ServiceException(ResultCode.ERROR_SIGNATURE_QRCODE_USER, ResultCode.ERROR_SIGNATURE_QRCODE_USER.getMessage());
        }

        if (Objects.isNull(userInfoResultDTO)) {
            throw new ServiceException(ResultCode.ERROR_SIGNATURE_QRCODE_USER, ResultCode.ERROR_SIGNATURE_QRCODE_USER.getMessage());
        }
        //请求唯一流水号
        String reqTid = JwtConstant.SIGN_QR_SCAN_PREFIX + IdUtil.fastSimpleUUID();
        String newToken = JwtProvider.createJWT(CebsConstant.TOKEN_EXPIRE_SECONDS, IRequestUtil.getApplicationId(), IRequestUtil.getApplicationUserId(), IRequestUtil.getBizNo(), reqTid, qrCodeScanDTO.getJwtProperties().getKey());
        vo.setToken(newToken);
        return vo;
    }

    /**
     * 获取印章列表
     * @param cebsSignatureDTO
     * @return
     */
    public static List<GetUserSealsVO> getUserSeals(CebsSignatureDTO cebsSignatureDTO) {
        // 初始化Ca
        CebsConfiguration.init(cebsSignatureDTO.getCebsSdkProperties());
        // 获取扫码用户信息
        GetElectronicSealSignatureUserInfoParamDTO userInfoParamDTO = new GetElectronicSealSignatureUserInfoParamDTO();
        userInfoParamDTO.setTid(cebsSignatureDTO.getPid());
        GetElectronicSealSignatureUserInfoResultDTO userInfoResultDTO = ElectronicSealSignature.getElectronicSealSignatureUserInfo(userInfoParamDTO);
        // 构造请求参数
        GetUserSealsParamDTO paramDTO = new GetUserSealsParamDTO();
        paramDTO.setTid(userInfoResultDTO.getTid());
        paramDTO.setPid(cebsSignatureDTO.getPid());
        paramDTO.setSealBelongType(userInfoResultDTO.getSealSignatureUserType());
        paramDTO.setOrgTransactionCode(userInfoResultDTO.getOrgTransactionCode());
        paramDTO.setPersonalTransactionCode(userInfoResultDTO.getPersonalTransactionCode());
        paramDTO.setAccessToken(userInfoResultDTO.getAccessToken());
        paramDTO.setTradingSystemCode(cebsSignatureDTO.getCebsSdkProperties().getTradingSystemCode());
        paramDTO.setOrgCode(userInfoResultDTO.getOrgCode());
        paramDTO.setIdCardHash(userInfoResultDTO.getIdCardHash());
        log.info("调用SDK获取用户印章列表参数：{}", JSON.toJSONString(paramDTO));
        List<GetUserSealsResultDTO> resultDTOList =null;
        try {
            resultDTOList=ElectronicSealSignature.getUserSeals(paramDTO);
            log.info("调用SDK获取用户印章列表返回：{}", JSON.toJSONString(resultDTOList));
            if (resultDTOList==null || CollectionUtil.isEmpty(resultDTOList)) {
                throw new ServiceException(ResultCode.ERROR_USER_SEALS, ResultCode.ERROR_USER_SEALS.getMessage());
            }

        }catch (Exception e){
            throw new ServiceException(ResultCode.ERROR_USER_SEALS, ResultCode.ERROR_USER_SEALS.getMessage());
        }

//        log.info("调用SDK获取用户印章列表响应：{}", JSON.toJSONString(resultDTOList));
//        if (CollectionUtil.isEmpty(resultDTOList)) {
//            throw new ServiceException(ResultCode.FAIL, "未获取到用户印章列表");
//        }
        GetUserSealsVO sealsVO = null;
        List<GetUserSealsVO> voList = new ArrayList<>();
        for (GetUserSealsResultDTO resultDTO : resultDTOList) {
            sealsVO = new GetUserSealsVO();
            BeanUtils.copyProperties(resultDTO, sealsVO);
            sealsVO.setSealImageBase64(resultDTO.getSealImage());
            try {
//                SealSize sealImgSize = IFCAUtil.calculateSealSize(Base64Utils.decodeFromString(resultDTO.getSealImage()), cebsSignatureDTO.getSignProperties().getSealImgMaxValue());
                SealSize sealImgSize = null;
                //获取印章图片类型
                SealTypeEnum sealTypeEnum = SealTypeEnum.getByType(resultDTO.getSealType());
                if (Objects.isNull(sealTypeEnum)) {
                    log.info("未获取到印章图片类型{}枚举对象，使用默认图片大小", resultDTO.getSealType());
                    sealImgSize = IFCAUtil.calculateSealSize(Base64Utils.decodeFromString(resultDTO.getSealImage()), 113, 113);
                } else {
                    sealImgSize = IFCAUtil.calculateSealSize(Base64Utils.decodeFromString(resultDTO.getSealImage()), sealTypeEnum.getWidthPx(), sealTypeEnum.getHeightPx());
                }
                sealsVO.setWidth(sealImgSize.getWidth());
                sealsVO.setHeight(sealImgSize.getHeight());
            } catch (Exception e) {
                throw new ServiceException(ResultCode.ERROR_USER_SEALS_PHOTO, ResultCode.ERROR_USER_SEALS_PHOTO.getMessage());
            }
            voList.add(sealsVO);
        }
        return voList;
    }

    public static GetSignResultVO commitSign(StartSignDTO startSignDTO)  {
        // 初始化Ca
        CebsConfiguration.init(startSignDTO.getCebsSdkProperties());
        //本地文件路径
        String fileAbsolutePath = startSignDTO.getLocalFilePath();
        if (!FileUtil.exist(fileAbsolutePath)) {
            throw new ServiceException(ResultCode.ERROR_FILE_NOT_FOUND, ResultCode.ERROR_FILE_NOT_FOUND.getMessage());
        }
        //签章位置参数
        CommitSignInfoDTO signatureInfo = startSignDTO.getSignatureInfo();
        //PDF文件
        if (FileTypeEnum.PDF.getType().equals(startSignDTO.getAwaitingSignatureFileType())) {
            //PDF阅读器
            PdfReader pdfReader = null; 
            try {
                pdfReader = new PdfReader(fileAbsolutePath);
            } catch (Exception e) {
                throw new ServiceException(ResultCode.ERROR_FILE_PARSER, ResultCode.ERROR_FILE_PARSER.getMessage());
            }
            if (PositionTypeEnum.KEYWORD.getType().equals(startSignDTO.getPositionType())) {
                //判断关键字是否存在(关键字不存在指定页, pageNumber默认0代表所有页)
                boolean exists = PDFTools.isKeyWordExist(pdfReader, "0", signatureInfo.getKeyword());
                if (!exists) {
                    pdfReader.close();
                    log.error("文件：{}中未包含关键字：{}", startSignDTO.getFileName(), signatureInfo.getKeyword());
                    throw new ServiceException(ResultCode.ERROR_PDF_KEY_WORD, ResultCode.ERROR_PDF_KEY_WORD.getMessage());
                }
            }
            //重新计算传入的页码，解析连续页码后得到新的页码集合
            String newPages = ICommonUtil.parsePages(signatureInfo.getPage());
            //判断页码是否有效
            boolean exists = PDFTools.isMultiplePageNumbersExist(pdfReader, newPages);
            if (!exists) {
                pdfReader.close();
                throw new ServiceException(ResultCode.ERROR_PDF_PAGE, ResultCode.ERROR_PDF_PAGE.getMessage());
            }
            pdfReader.close();
        }
        String status= new ExecuteSignatureService().executeSignature(startSignDTO);
        //构造签署结果
        GetSignResultVO vo = GetSignResultVO.builder()
                .signStatus(status)
                .build();
        return vo;
    }
}
